<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
    //JavaScript的所有数据都可以看成对象，那是不是我们已经在使用面向对象编程了呢？
    //JavaScript的面向对象编程和大多数其他语言如Java、C#的面向对象编程都不太一样。如果你熟悉Java或C#，很好，你一定明白面向对象的两个基本概念：
    //1:类：类是对象的类型模板，例如，定义Student类来表示学生，类本身是一种类型，Student表示学生类型，但不表示任何具体的某个学生；
    //2:实例：实例是根据类创建的对象，例如，根据Student类可以创建出xiaoming、xiaohong、xiaojun等多个实例，每个实例表示一个具体的学生，他们全都属于Student类型。
    var Robat= {
        name:'Robat',
        height:1.6,
        run:function(){
            console.log(this.name +' is runing')
        }
    }
    var xiaoming = {
        name:'xiaoming',
    }
    var xiaozhang = {
        name:"xiaozhang"
    }
    console.log(xiaoming)
    xiaoming.__proto__ = Robat; // _ _ proto _ _ 两个下划线
    xiaozhang.__proto__ = xiaoming
    console.log(xiaozhang)
    console.log(xiaoming.name) // 有限调用自身，如果自身不存在调用原型 指向的对象
    console.log(xiaoming.height)
    xiaoming.run()
    var Brid = {
        name:'xiaoniao',
        fly:function(){
            console.log(this.name +' is flying')
        },
    }
    xiaoming.__proto__ = Brid;
    xiaoming.fly()
    try {
        xiaoming.run()
    } catch (e) {
        console.log(e) //报错
    }
    //编写JavaScript代码时，不要直接用obj.__proto__去改变一个对象的原型，并且，低版本的IE也无法使用__proto__。Object.create()方法可以传入一个原型对象，
    //并创建一个基于该原型的新对象，但是新对象什么属性都没有，因此，我们可以编写一个函数来创建xiaoming：
    function createBird(name){
       var s = Object.create(Brid);
       s.name = name;
       return s
    }
    var bigBird = createBird('daniao');
    bigBird.fly();
    //Object.create() 方法创建一个拥有指定原型和若干个指定属性的对象
    //Object.create(proto, [ propertiesObject ])
    //@param1:一个对象，应该是新创建的对象的原型;
    //@param2:propertiesObject: 对象，可选参数，为新创建的对象指定属性对象。该属性对象可能包含以下值：
    var t = Object.create(Brid,{
       'a':{value:'我是a',configurable:true,enumerable:false,writable:true,}
    })
    t.a = "你是"; //configurable：默认false，为true表示改对象属性是否可更改 enumerable表示是否课枚举 writable为true。表示改对象键值不可更改
    console.log(t)
    for (var key in t) {
        console.log(key) //name fly a没有被枚举
    }
    
</script>
</body>
</html>